package com.xcity.pomelo.response;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import com.xcity.db.entity.Employee;
import com.xcity.db.entity.Player;
import com.xcity.game.combat.CombatUtils;
import com.xcity.game.combat.unit.Combatable;
import com.xcity.game.combat.unit.CombatableBase;
import com.xcity.game.formation.Formation;
import com.xcity.game.npc.NpcTemplate;
import com.xcity.game.peakroad.combat.PeakRoadCombatable;
import com.xcity.game.skill.Skill;

import naga.x.net.impl.pomelo.PomeloMessage;
import naga.x.net.impl.pomelo.protocol.Message;

@PomeloMessage(type = Message.Type.RESPONSE)
public class CombatInfoResponse extends Response {
	
	public byte formatType; // 使用的战斗阵型
	public Team source, target;
	public int timeLimit; // 战斗限时（秒）（-1：不限时）
//	public int roundLimit; // 回合限制
//	public List<ItemResponse> items = Collections.emptyList();
	
	public static class TeamBuilder {
		private Player playerLeader;
		private List<Employee> employeeMembers;
		private NpcTemplate npcLeader;
		private List<NpcTemplate> npcMembers;
		private Combatable leader;
		private List<Combatable> members;
		public TeamBuilder setLeader(Player leader) {
			this.playerLeader = leader;
			return this;
		}
		public TeamBuilder setLeader(NpcTemplate leader) {
			this.npcLeader = leader;
			return this;
		}
		public TeamBuilder setLeader(Combatable leader) {
			this.leader = leader;
			return this;
		}
		public TeamBuilder addMember(Employee member) {
			if (employeeMembers == null)
				employeeMembers = new ArrayList<>(4);
			employeeMembers.add(member);
			return this;
		}
		/**
		 * @see #addMember(Employee)
		 * @see #addMember(Combatable)
		 */
		@Deprecated
		public TeamBuilder addEmployeeMember(long employeeId) {
			if (playerLeader == null) {
				throw new NullPointerException("The playerLeader is null");
			}
			if (employeeMembers == null)
				employeeMembers = new ArrayList<>(4);
			if (employeeId == 0L) {
				employeeMembers.add(null);
			} else {
				Employee e = playerLeader.getEmployees().get(employeeId);
				employeeMembers.add(e);
			}
			return this;
		}
		public TeamBuilder addMember(NpcTemplate member) {
			if (npcMembers == null)
				npcMembers = new ArrayList<>(4);
			npcMembers.add(member);
			return this;
		}
		public TeamBuilder addMember(Combatable member) {
			if (members == null)
				members = new ArrayList<>(4);
			members.add(member);
			return this;
		}
		public TeamBuilder setMembers(List<Combatable> members) {
			this.members = members;
			return this;
		}
		private static List<MemberSkill> wrapSkills(Combatable c) {
			List<? extends Skill> refers = c.getSkills();
			if (refers == null) {
				return Collections.emptyList();
			}
			List<MemberSkill> skills = new ArrayList<MemberSkill>(1);
			for (int i = 0; i < refers.size(); i++) {
				Skill refer = refers.get(i);
				MemberSkill ms = new MemberSkill();
				skills.add(ms);
				ms.id = refer.getId();
				ms.name = refer.getName();
				ms.desc = refer.getDesc();
				ms.icon = refer.getIcon();
				ms.mp = refer.getTemplate().getMp();
			}
			return skills;
		}
		public Team build() {
			Team team = new Team();
			TeamMember leader = null;
			int combatPower = 0;
			if (playerLeader != null) {
				leader = buildMember(playerLeader);
			} else if (npcLeader != null) {
				leader = buildMember(npcLeader.toCombatabale());
			} else if (this.leader != null) {
				leader = buildMember(this.leader);
			} else {
				leader = TeamMember.EMPTY;
			}
			team.leader = leader;
			combatPower += leader.combatPower;
			if (team.members == null) {
				team.members = new ArrayList<>(4);
			}
			if (employeeMembers != null) {
				for (int i = 0; i < employeeMembers.size(); i++) {
					Employee e = employeeMembers.get(i);
					TeamMember tm = e != null ? buildMember(e) : TeamMember.EMPTY;
					combatPower += tm.combatPower;
					team.members.add(tm);
				}
			}
			if (npcMembers != null) {
				for (int i = 0; i < npcMembers.size(); i++) {
					NpcTemplate npc = npcMembers.get(i);
					TeamMember tm = npc != null ? buildMember(npc.toCombatabale()) : TeamMember.EMPTY;
					combatPower += tm.combatPower;
					team.members.add(tm);
				}
			}
			if (members != null) {
				for (int i = 0; i < members.size(); i++) {
					Combatable c = members.get(i);
					TeamMember tm = c != null ? buildMember(c) : TeamMember.EMPTY;
					combatPower += tm.combatPower;
					team.members.add(tm);
				}
			}
			fillEmpty(team);
			team.combatPower = combatPower;
			return team;
		}
		private static TeamMember buildMember(Combatable c) {
			TeamMember tm = new TeamMember();
			tm.id = c.getId();
			tm.sex = c.getSex();
			tm.name = c.getName();
			tm.icon = c.getIcon();
			tm.level = c.getLevel();
			tm.hp = c.getHp();
			tm.maxHp = c.getMaxHp();
			tm.combatPower = CombatUtils.calcCombatPower((CombatableBase) c);
			tm.skills = wrapSkills(c);
			
			if (c instanceof PeakRoadCombatable) {
				c = ((PeakRoadCombatable) c).refer();
			}
			if (c instanceof Player) {
				tm.qualityLvl = ((Player) c).getQualityLvl();
			} else if (c instanceof Employee) {
				tm.qualityLvl = ((Employee) c).getQualityLvl();
			}
			return tm;
		}
	}
	
	public static class Team {
		public int combatPower; // 战斗力
		public TeamMember leader;
		public List<TeamMember> members;
		public Team() {}
	}
	
	public static class TeamMember/* implements GameUnit*/ {
		public long id;
		public byte sex;
		public String name = "";
		public String icon = "";
		public int level;
		public int hp, maxHp;
		public int combatPower;
		public List<MemberSkill> skills = Collections.emptyList();
		public int qualityLvl;
		
		static final TeamMember EMPTY = new TeamMember();
		
		public TeamMember() {}
	}
	
	public static class MemberSkill {
		public int id;
		public String name;
		public String desc;
		public String icon;
		public int mp;
	}
	
	public CombatInfoResponse(int serial) {
		super(serial);
	}

	public CombatInfoResponse(int serial, Team source, Team target, byte formatType) {
		this(serial, source, target, formatType, -1);
	}
	
	public CombatInfoResponse(int serial, Team source, Team target, byte formatType, int timeLimit) {
		super(serial);
		this.formatType = formatType;
		this.source = source;
		this.target = target;
		this.timeLimit = timeLimit;
	}

	// 补齐空位
	private static void fillEmpty(Team team) {
		int n = Formation.FORMATION_CAPCITY - team.members.size();
		while (--n >= 0) {
			team.members.add(TeamMember.EMPTY);
		}
	}
	
}
